package com.bygf.curve.axis;

import com.bygf.curve.panel.ChartPanel;
import com.bygf.curve.utils.Utils;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.text.DecimalFormat;

/**
 * Y坐标轴
 *
 * @author sunyupei
 */
public class YAxis extends Axis {

    //坐标格式化对象
    private DecimalFormat format = new DecimalFormat("#");

    /**
     * 构造方法
     *
     * @param chartPanel
     * @param title 坐标轴标题
     */
    public YAxis(ChartPanel chartPanel, String title) {
        this.chartPanel = chartPanel;
        this.title = title;
        this.setOpaque(false);
    }

    /**
     * 绘制坐标轴标题
     *
     * @param g
     */
    private void drawTitle(Graphics2D g) {
        g.setColor(titleColor);
        g.setFont(titleFont);
        AffineTransform affBack = g.getTransform();
        AffineTransform aff = g.getTransform();
        double rotateX = this.getWidth() / 2;
        double rotateY = this.getHeight() * 1F / 2;
        double titleWidth = Utils.getStringWidth(title, titleFont);
        aff.rotate(Math.toRadians(-90), rotateX, rotateY);
        g.setTransform(aff);
        g.drawString(title, (int) (this.getWidth() - titleWidth) / 2, this.getHeight() / 2 - 15);
        g.setTransform(affBack);
    }

    /**
     * 绘制刻度线及刻度单位
     *
     * @param g
     */
    private void drawMarkLine(Graphics2D g) {
        drawStart = 0;
        drawEnd = this.getHeight();
        g.setColor(lineColor);
        g.drawLine(this.getWidth() - 1, drawStart, this.getWidth() - 1, drawEnd);
        double mark = this.getHeight() * 1F / chartPanel.getYGridLineCount();
        double valueMark = (getEndValueNow() - getStartValueNow()) / chartPanel.getYGridLineCount();
        for (int i = 0; i <= chartPanel.getYGridLineCount(); i++) {
            double x1 = this.getWidth() - 6;
            double y1 = this.getHeight() - i * mark;
            if (y1 <= 0) {
                y1 = 1;
            } else if (y1 == this.getHeight()) {
                y1 = this.getHeight() - 1;
            }
            double x2 = this.getWidth() - 1;
            Line2D line = new Line2D.Double(x1, y1, x2, y1);
            g.draw(line);
            String str = format.format(valueMark * i + getStartValueNow());
            float x = this.getWidth() - Utils.getStringWidth(str, titleFont) - 8;
            float y = (float) (this.getHeight() - i * mark + titleFont.getSize() / 2);
            if (i == 0) {
                y = (float) (this.getHeight() - i * mark);
            } else if (i == chartPanel.getYGridLineCount()) {
                y = (float) (this.getHeight() - i * mark + titleFont.getSize());
            }
            g.drawString(str, x, y);
        }
    }

    /**
     * 双缓冲绘制
     *
     * @param g
     */
    private void doubleBuffer(Graphics2D g) {
        g.setStroke(stroke);
        drawTitle(g);
        drawMarkLine(g);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        BufferedImage bufferedImage = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = bufferedImage.createGraphics();
        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//        rh.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
        rh.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
        rh.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g2.setRenderingHints(rh);
        doubleBuffer(g2);
        g.drawImage(bufferedImage, 0, 0, null);
    }

    @Override
    public double valueToPix(double value) {
        return chartPanel.getCurvePanel().getHeight() - (value - getStartValueNow())
                / (getEndValueNow() - getStartValueNow()) * chartPanel.getCurvePanel().getHeight();
    }

    @Override
    public double PixToValue(double pix) {
        return (1 - pix / chartPanel.getCurvePanel().getHeight()) * (getEndValueNow() - getStartValueNow()) + getStartValueNow();
    }

    /**
     * @return the format
     */
    public DecimalFormat getDecimalFormat() {
        return format;
    }

    /**
     * @param format the format to set
     */
    public void setDecimalFormat(DecimalFormat format) {
        this.format = format;
    }

    @Override
    public boolean setValueCheck(double startValueNow, double endValueNow) {
        double valueCha = (endValueNow - startValueNow) / chartPanel.getXGridLineCount();
        double minCha = 1D / Math.pow(10, format.getMaximumFractionDigits());
        return valueCha >= minCha;
    }
    
    @Override
    public void setStartValueNow(double startValueNow) {
        this.startValueNow = Double.parseDouble(format.format(startValueNow));
        this.repaint();
        if (listener != null) {
            listener.axisChanged(this);
        }
    }
    
    @Override
    public void setEndValueNow(double endValueNow) {
        this.endValueNow = Double.parseDouble(format.format(endValueNow));
        this.repaint();
        if (listener != null) {
            listener.axisChanged(this);
        }
    }
}
